//: [Previous](@previous)

import Foundation


func download(gameList: [String]) {
    let queue = DispatchQueue.global()
    queue.async {
        gameList.forEach { game in
            let sema = DispatchSemaphore(value: 0)
            print("\(game) 做任务",Thread.current)
            sleep(2)
            sema.signal()
            print("\(game) before wait")
            sema.wait()
            print("\(game) after wait")
        }
    }
}
//download(gameList: ["a", "b", "c", "d"])


var str = "Hello, playground"

let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())

func timerTest() {
    var remainingTime = 10 * 60 * 1000
    timer.schedule(deadline: .now(), repeating: DispatchTimeInterval.milliseconds(100))
    timer.setEventHandler(handler: {
        remainingTime -= 100
        let minutes = remainingTime / 1000 / 60;
        let second = (remainingTime - minutes * 60 * 1000) / 1000
//        let second = (remainingTime / 1000) % 60
        let msec = remainingTime - (minutes * 60 + second) * 1000;
        print("\(remainingTime) \(minutes):\(second):\(msec)")
    })
    timer.resume()
    print("bb")
}

//timerTest()


/*
 对于加入到group中的任务，如果在group_notify的回调执行前添加到group中，对于当前notify，都是有效的
 对于在notify的回调执行后，加入到group中的任务，notify是无效的
 */
func gcdGroupTest() {
    let group = DispatchGroup.init()
    //添加任务
    DispatchQueue.global().async(group: group, qos: DispatchQoS.default, flags: .enforceQoS) {
        print("\(Date()), 任务1 开始")
        sleep(3)
        print("\(Date()), 任务1 结束")
    }
    
    DispatchQueue.global().async(group: group, qos: .default, flags: .enforceQoS) {
        print("\(Date()), 任务2 开始")
        sleep(2)
        print("\(Date()), 任务2 结束")
        
        DispatchQueue.global().async(group: group, qos: .default, flags: .enforceQoS) {
            print("\(Date()), 任务3 开始")
            sleep(1)
            print("\(Date()), 任务3 结束")
        }
    }
    
    DispatchQueue.global().async(group: group, qos: .default, flags: .enforceQoS) {
        print("\(Date()), 任务4 开始")
        sleep(2)
        print("\(Date()), 任务4 结束")
    }
    DispatchQueue.global().async(group: group, qos: .default, flags: .enforceQoS) {
        print("\(Date()), 任务5 开始")
        sleep(3)
        print("\(Date()), 任务5 结束")
    }
    
    group.notify(queue: DispatchQueue.global()) {
        print("\(Date()), group内所有任务完成")
    }
}
//gcdGroupTest()


//信号量测试
/*
 通过信号量控制GCD的最大并发
 1. 初始一个信号量，value为最大并发数
 2. 信号量wait（-1）
 3. 信号量signl（+1）
 当value = 0时阻塞，不在添加任务
 当value > 0时，添加任务到队列
 */
func sempTest() {
    let sema = DispatchSemaphore(value: 3)
    for i in 0..<10 {
        //任务开始，信号-1
        sema.wait()
        DispatchQueue.global().async {
            sleep(3)
            print("\(i)做任务",Thread.current)
            //任务完成，信号+1
            sema.signal()
        }
    }
}
//sempTest()


// MARK: - 同步异步
func threadTest() {
    // 创建一个串行队列
    let queue = DispatchQueue(label: "串行", qos: .default, attributes: .init(rawValue: 0), autoreleaseFrequency: .inherit, target: nil)
    //异步执行
    queue.async {
        print("异步: \(Thread.current)")
    }
    //同步执行
    queue.sync {
        print("同步: \(Thread.current)")
    }
}
//threadTest()



//dispatch_barrier探究
/*
同步,异步,都会阻断队列的任务执行
区别在于,异步执行,不影响后面代码的执行
同步执行,后面的代码不会早于这个barrier块
*/
func barrierTest1() {
    print("start")
    let queue = DispatchQueue(label: "test1", qos: .default, attributes: .concurrent, autoreleaseFrequency:.inherit, target: nil)
    //异步执行
    queue.async {
        print("1__\(Thread.current)")
    }
    queue.async {
        print("2__\(Thread.current)")
    }
    queue.sync(flags: .barrier) {
        print("++++++barrier++++++,\(Thread.current)")
    }
    print("试一下")
    queue.async {
        print("3__\(Thread.current)")
    }
    queue.async {
        print("4__\(Thread.current)")
    }
    queue.async {
        print("5__\(Thread.current)")
    }
    print("end")
    
    
}
//barrierTest1()

